home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * NFS-HANDLER.C V1.11 27-June-89
- *
- * DNet DOS level NFS handler.
- *
- * By Matthew Dillon.
- *
- * This handler converts DOS packets into a form suitable for transmission
- * over a DNet link to a remote server which will execute the operations.
- */
-
- #include "dos.h"
- #include <exec/alerts.h>
-
- /*
- * Since this code might be called several times in a row without being
- * unloaded, you CANNOT ASSUME GLOBALS HAVE BEEN ZERO'D!! This also goes
- * for any global/static assignments that might be changed by running the
- * code.
- */
-
- PROC *DosProc; /* Our Process */
- DEVNODE *DosNode; /* Our DOS node.. created by DOS for us */
- DEVLIST *DevList; /* Device List structure for our volume node */
-
- void *SysBase; /* EXEC library base */
- /*
- void *DResBase;
- */
-
- DOSLIB *DOSBase; /* DOS library base for debug process */
- MLIST FHBase; /* Open Files */
- MLIST LCBase; /* Open Locks */
-
- long TotalBytes; /* total bytes of data in filesystem */
-
- void *CHan; /* DNet channel */
- HANDLE RFRoot;
-
- char TmpBuf[256];
-
- #ifdef DEBUG
- short DBDisable = 0; /* Debug code */
- #endif
-
-
- HANDLE *AllocHandle();
-
- /*
- * Don't call the entry point main(). This way, if you make a mistake
- * with the compile options you'll get a link error.
- */
-
- void __saveds noname ARGS((void));
-
- void returnpacket ARGS((PACKET *));
- int packetsqueued ARGS((void));
- HANDLE *GetHandleForLock ARGS((LOCK *));
- void *GetLockForHandle ARGS((HANDLE *));
- HANDLE *AllocHandle ARGS((char *, RtOpen *));
- void FreeHandle ARGS((HANDLE *));
- void *dosalloc ARGS((ulong));
- void dosfree ARGS((ulong *));
- char *bstos ARGS((ubyte *));
- char *skipdevice ARGS((char *));
- int DoNetworkOp ARGS((char, void *, int, void *, int, void *, int));
-
- void __saveds
- noname()
- {
- reg PACKET *packet;
- reg short error;
- MSG *msg;
- ubyte notdone;
- void *tmp;
-
- #ifndef LATTICE
- mygeta4();
- #endif
-
- /*
- * Initialize all global variables. SysBase MUST be initialized before
- * we can make Exec calls.
- */
-
- TotalBytes = 0;
- SysBase = *(void **)4;
- DOSBase = (void *)OpenLibrary("dos.library",0);
- /*
- DResBase= OpenLibrary("dres.library",0);
- */
- DosProc = (PROC *)FindTask(NULL);
- CHan = 0;
- {
- WaitPort(&DosProc->pr_MsgPort); /* Get Startup Packet */
- msg = GetMsg(&DosProc->pr_MsgPort);
- packet = (PACKET *)msg->mn_Node.ln_Name;
-
- /*
- * Loading DosNode->dn_Task causes DOS *NOT* to startup a new
- * instance of the device driver for every reference. E.G. if
- * you were writing a CON device you would want this field to
- * be NULL.
- */
-
- if (DOSBase /*&& DResBase*/) {
- DOSINFO *di = BTOC(((ROOTNODE *)DOSBase->dl_Root)->rn_Info);
- register DEVLIST *dl = dosalloc(sizeof(DEVLIST));
-
- DosNode = BTOC(packet->dp_Arg3);
- DosNode->dn_Task = &DosProc->pr_MsgPort;
-
- /*
- * Create Volume node and add to the device list. This will
- * cause the WORKBENCH to recognize us as a disk. If we don't
- * create a Volume node, Wb will not recognize us. However,
- * we are a RAM: disk, Volume node or not.
- */
-
- DevList = dl;
- dl->dl_Type = DLT_VOLUME;
- dl->dl_Task = &DosProc->pr_MsgPort;
- dl->dl_DiskType = ID_DOS_DISK;
- dl->dl_Name = (BSTR)DosNode->dn_Name;
- dl->dl_Next = di->di_DevInfo;
- di->di_DevInfo = (long)CTOB(dl);
-
- packet->dp_Res1 = DOS_TRUE;
- packet->dp_Res2 = 0;
- } else { /* couldn't open dos.library */
- packet->dp_Res1 = DOS_FALSE;
- returnpacket(packet);
- return; /* exit process */
- }
- returnpacket(packet);
- }
-
- /* Initialize RAM disk */
- #ifdef DEBUG
- dbinit();
- #endif
-
- {
- NewList((LIST *)&FHBase); /* more globals */
- NewList((LIST *)&LCBase);
-
- BZero(&RFRoot, sizeof(RFRoot));
- DateStamp((long *)&RFRoot.Date);
- RFRoot.Type = FILE_DIR;
- RFRoot.Name = "Root";
- }
-
- /*
- * Here begins the endless loop, waiting for requests over our
- * message port and executing them. Since requests are sent over
- * our message port, this precludes being able to call DOS functions
- * ourselves (that is why the debugging routines are a separate process)
- */
-
- top:
- for (notdone = 1; notdone;) {
- WaitPort(&DosProc->pr_MsgPort);
- while (msg = GetMsg(&DosProc->pr_MsgPort)) {
- packet = (PACKET *)msg->mn_Node.ln_Name;
- packet->dp_Res1 = DOS_TRUE;
- packet->dp_Res2 = 0;
- error = 0;
-
- if (!CHan) { /* attempt to open server channel */
- CHan = DOpen(NULL, PORT_NFS, -80, -80);
- if (!CHan) { /* otherwise giveup! */
- notdone = 0;
- goto fail;
- }
- }
-
- #ifdef DEBUG
- dbprintf("ACTION %ld\n", packet->dp_Type);
- #endif
- switch(packet->dp_Type) {
- case ACTION_DIE: /* attempt to die? */
- notdone = 0; /* try to die */
- break;
- case ACTION_OPENRW: /* FileHandle,Lock,Name Bool */
- case ACTION_OPENOLD: /* FileHandle,Lock,Name Bool */
- case ACTION_OPENNEW: /* FileHandle,Lock,Name Bool */
- {
- OpOpen opkt;
- RtOpen rpkt;
- short r;
- char *name = skipdevice(bstos((ubyte *)packet->dp_Arg3));
- HANDLE *handle;
-
- opkt.DirHandle = GetHandleForLock((LOCK *)packet->dp_Arg2)->Handle;
- opkt.Modes = packet->dp_Type;
-
- r = DoNetworkOp('O',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
- if (r) {
- error = ERROR_OBJECT_IN_USE;
- } else if (rpkt.Handle == -1) {
- error = ERROR_OBJECT_NOT_FOUND;
- } else if (rpkt.Type > 0) { /* can't open dir */
- OpClose opkt;
-
- opkt.Handle = rpkt.Handle;
- DoNetworkOp('C',&opkt,sizeof(opkt),NULL,0,NULL,0);
- error = ERROR_OBJECT_WRONG_TYPE;
- } else {
- if (name[0] == 0)
- name = GetHandleForLock((LOCK *)packet->dp_Arg2)->Name;
- handle = AllocHandle(name, &rpkt);
- ((FH *)BTOC(packet->dp_Arg1))->fh_Arg1 = (long)handle;
- }
- }
- break;
- case ACTION_READ: /* FHArg1,CPTRBuffer,Length ActLength */
- {
- HANDLE *handle = (HANDLE *)packet->dp_Arg1;
- OpRead opkt;
- RtRead rpkt;
- short err;
-
- opkt.Handle = handle->Handle;
- opkt.Bytes = packet->dp_Arg3;
-
- err = DoNetworkOp('R',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
- if (err)
- rpkt.Bytes = -1;
- if (rpkt.Bytes > 0 && rpkt.Bytes <= opkt.Bytes)
- DRead(CHan, (void *)packet->dp_Arg2, rpkt.Bytes);
- packet->dp_Res1 = rpkt.Bytes;
- }
- break;
- case ACTION_WRITE: /* FHArg1,CPTRBuffer,Length ActLength */
- {
- HANDLE *handle = (HANDLE *)packet->dp_Arg1;
- OpWrite opkt;
- RtWrite rpkt;
- short err;
-
- opkt.Handle = handle->Handle;
- opkt.Bytes = packet->dp_Arg3;
-
- err = DoNetworkOp('W',&opkt,sizeof(opkt),(void *)packet->dp_Arg2,packet->dp_Arg3,&rpkt,sizeof(rpkt));
-
- if (err)
- rpkt.Bytes = -1;
- packet->dp_Res1 = rpkt.Bytes;
- }
- break;
- case ACTION_CLOSE: /* FHArg1 Bool:TRUE */
- {
- HANDLE *handle = (HANDLE *)packet->dp_Arg1;
- OpClose opkt;
-
- if (packet->dp_Arg1 == NULL || handle->Magic != MAGIC) {
- Alert(AT_Recovery|0, (char *)0x12345555);
- } else {
- opkt.Handle = handle->Handle;
-
- DoNetworkOp('C',&opkt,sizeof(opkt),NULL,0,NULL,0);
- FreeHandle(handle);
- }
- }
- if (!GetHead(&FHBase))
- notdone = 0;
- break;
- case ACTION_SEEK: /* FHArg1,Position,Mode OldPosition*/
- {
- HANDLE *handle = (HANDLE *)packet->dp_Arg1;
- OpSeek opkt;
- RtSeek rpkt;
- short err;
-
- opkt.Handle = handle->Handle;
- opkt.Offset = packet->dp_Arg2;
- opkt.How = packet->dp_Arg3 + 1;
-
- err = DoNetworkOp('S',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
- if (err)
- rpkt.NewOffset = -1;
- if (rpkt.NewOffset < 0)
- error = ERROR_SEEK_ERROR;
- else
- packet->dp_Res1 = rpkt.OldOffset;
- }
- break;
- case ACTION_EXAMINE_NEXT: /* Lock,Fib Bool */
- {
- HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
- register FIB *fib = BTOC(packet->dp_Arg2);
- OpNextDir opkt;
- RtNextDir rpkt;
- short err;
-
- #ifdef DEBUG
- dbprintf("FIB = %08lx\n", fib);
- #endif
- if (handle->Type < 0) {
- error = ERROR_OBJECT_WRONG_TYPE;
- break;
- }
-
- opkt.Handle = handle->Handle;
- opkt.Index = fib->fib_DiskKey;
- err = DoNetworkOp('N',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
- if (err || rpkt.Handle == -1) {
- error = ERROR_NO_MORE_ENTRIES;
- } else { /* not a real file handle, just info & name */
- unsigned char fn;
-
- if (DRead(CHan, &fn, 1) != 1)
- TmpBuf[fn = 0] = 0;
- if (DRead(CHan, TmpBuf, fn) != fn)
- TmpBuf[fn = 0] = 0;
- ++fib->fib_DiskKey; /* next key */
- fib->fib_DirEntryType = rpkt.Type;
- fib->fib_Protection = rpkt.Prot;
- fib->fib_EntryType = NULL;
- fib->fib_Size = rpkt.Size;
- fib->fib_NumBlocks = rpkt.Size >> 9;
- if (strlen(TmpBuf) >= sizeof(fib->fib_FileName) - 2) {
- fib->fib_FileName[0] = 1;
- fib->fib_FileName[1] = '?';
- fib->fib_FileName[2] = 0;
- } else {
- strcpy(fib->fib_FileName+1, TmpBuf);
- fib->fib_FileName[0] = strlen(TmpBuf);
- }
- fib->fib_Comment[0] = 0;
- fib->fib_Comment[1] = 0;
- fib->fib_Date = rpkt.Date;
- }
- }
- break;
- case ACTION_EXAMINE_OBJECT: /* Lock,Fib Bool */
- {
- HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
- register FIB *fib = BTOC(packet->dp_Arg2);
-
- #ifdef DEBUG
- dbprintf("FIB = %08lx\n", fib);
- #endif
- fib->fib_DiskKey = 0;
- fib->fib_DirEntryType = handle->Type;
- /*
- * fib->fib_FileName bcpl type string
- */
- fib->fib_Protection = handle->Prot;
- fib->fib_EntryType = NULL;
- fib->fib_Size = handle->Size;
- fib->fib_NumBlocks = handle->Size >> 9;
-
- if (strlen(handle->Name) >= sizeof(fib->fib_FileName) - 2) {
- fib->fib_FileName[0] = 1;
- fib->fib_FileName[1] = '?';
- fib->fib_FileName[2] = 0;
- } else {
- strcpy(fib->fib_FileName+1, handle->Name);
- fib->fib_FileName[0] = strlen(handle->Name);
- }
- fib->fib_Comment[0] = 0;
- fib->fib_Comment[1] = 0;
- fib->fib_Date = handle->Date;
- }
- break;
- case ACTION_INFO: /* Lock, InfoData Bool:TRUE */
- tmp = BTOC(packet->dp_Arg2);
- error = -1;
- /* fall through */
- case ACTION_DISK_INFO: /* InfoData Bool:TRUE */
- {
- register INFODATA *id;
-
- /*
- * Note: id_NumBlocks is never 0, but only to get
- * around a bug I found in my shell (where I divide
- * by id_NumBlocks). Other programs probably break
- * as well.
- */
-
- (error) ? (id = tmp) : (id = BTOC(packet->dp_Arg1));
- error = 0;
- BZero(id, sizeof(*id));
- id->id_DiskState = ID_VALIDATED;
- id->id_NumBlocks = (TotalBytes >> 9) + 1;
- id->id_NumBlocksUsed = (TotalBytes >> 9) + 1;
- id->id_BytesPerBlock = 512;
- id->id_DiskType = ID_DOS_DISK;
- id->id_VolumeNode = (long)CTOB(DosNode);
- id->id_InUse = (long)GetHead(&LCBase);
- }
- break;
- case ACTION_PARENT: /* Lock ParentLock */
- {
- HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
- OpParent opkt;
- RtParent rpkt;
- short err;
-
- opkt.Handle = handle->Handle;
-
- err = DoNetworkOp('P',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
- if (err)
- rpkt.Handle = NULL;
- if (rpkt.Handle == -1) {
- error = ERROR_OBJECT_NOT_FOUND;
- } else { /* create a file handle and return a lock */
- HANDLE *newhandle;
- unsigned char fn;
-
- if (DRead(CHan, &fn, 1) != 1)
- TmpBuf[fn = 0] = 0;
- if (DRead(CHan, TmpBuf, fn) != fn)
- TmpBuf[fn = 0] = 0;
- newhandle = AllocHandle(TmpBuf, &rpkt);
- packet->dp_Res1 = (long)GetLockForHandle(newhandle);
- }
- }
- break;
- case ACTION_DELETE_OBJECT: /*Lock,Name Bool */
- {
- OpDelete opkt;
- RtDelete rpkt;
- short err;
- char *name = skipdevice(bstos((ubyte *)packet->dp_Arg2));
-
- opkt.DirHandle = GetHandleForLock((LOCK *)packet->dp_Arg1)->Handle;
-
- err = DoNetworkOp('D',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
- if (err || rpkt.Error)
- error = ERROR_OBJECT_NOT_FOUND;
- }
- break;
- case ACTION_CREATE_DIR: /* Lock,Name Lock */
- {
- OpCreateDir opkt;
- RtCreateDir rpkt;
- short err;
- char *name = skipdevice(bstos((ubyte *)packet->dp_Arg2));
-
- opkt.DirHandle = GetHandleForLock((LOCK *)packet->dp_Arg1)->Handle;
-
- err = DoNetworkOp('M',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
- if (err)
- rpkt.Handle = NULL;
- if (rpkt.Handle == -1) {
- error = ERROR_OBJECT_EXISTS;
- } else { /* create a file handle and return a lock */
- HANDLE *newhandle = AllocHandle(name, &rpkt);
-
- packet->dp_Res1 = (long)GetLockForHandle(newhandle);
- }
- }
- break;
- case ACTION_LOCATE_OBJECT: /* Lock,Name,Mode Lock */
- {
- OpOpen opkt;
- RtOpen rpkt;
- short err;
- char *name = skipdevice(bstos((ubyte *)packet->dp_Arg2));
- HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
-
- opkt.DirHandle = handle->Handle;
- opkt.Modes = 1005;
-
- err = DoNetworkOp('O',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
- if (err) {
- error = ERROR_OBJECT_IN_USE;
- } else if (rpkt.Handle == -1) {
- error = ERROR_OBJECT_NOT_FOUND;
- } else {
- HANDLE *newhandle;
- if (name[0] == 0)
- name = handle->Name;
-
- newhandle = AllocHandle(name, &rpkt);
- packet->dp_Res1 = (long)GetLockForHandle(newhandle);
- }
- }
- break;
- case ACTION_COPY_DIR: /* Lock, Lock */
- {
- OpDup opkt;
- RtDup rpkt;
- short err;
- HANDLE *oldhandle = GetHandleForLock((LOCK *)packet->dp_Arg1);
-
- opkt.Handle = oldhandle->Handle;
-
- err = DoNetworkOp('d',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
- if (err) {
- error = ERROR_OBJECT_IN_USE;
- } else if (rpkt.Handle == -1) {
- error = ERROR_OBJECT_NOT_FOUND;
- } else {
- HANDLE *handle = AllocHandle(oldhandle->Name, &rpkt);
-
- packet->dp_Res1 = (long)GetLockForHandle(handle);
- }
- }
- break;
- case ACTION_FREE_LOCK: /* Lock, Bool */
- {
- HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
- OpClose opkt;
-
- opkt.Handle = handle->Handle;
-
- DoNetworkOp('C',&opkt,sizeof(opkt),NULL,0,NULL,0);
- FreeHandle(handle);
- }
- break;
- case ACTION_SET_PROTECT:/* -,Lock,Name,Mask Bool */
- error = ERROR_ACTION_NOT_KNOWN;
- break;
- case ACTION_SET_COMMENT:/* -,Lock,Name,Comment Bool */
- error = ERROR_ACTION_NOT_KNOWN;
- break;
- case ACTION_RENAME_OBJECT:/* SLock,SName,DLock,DName Bool */
- {
- OpRename opkt;
- RtRename rpkt;
- short err;
- char *name1= skipdevice(bstos((ubyte *)packet->dp_Arg2));
- char *name2= skipdevice(bstos((ubyte *)packet->dp_Arg4));
- short len1 = strlen(name1);
- short len2 = strlen(name2);
- char *name = AllocMem(len1+len2+2, MEMF_PUBLIC);
-
- opkt.DirHandle1 = GetHandleForLock((LOCK *)packet->dp_Arg1)->Handle;
- opkt.DirHandle2 = GetHandleForLock((LOCK *)packet->dp_Arg3)->Handle;
- strcpy(name, name1);
- strcpy(name+len1+1,name2);
-
- err = DoNetworkOp('r',&opkt,sizeof(opkt),name,len1+len2+2,&rpkt,sizeof(rpkt));
- FreeMem(name, len1+len2+2);
- if (err) {
- error = ERROR_OBJECT_IN_USE;
- } else if (rpkt.Error) {
- error = ERROR_OBJECT_NOT_FOUND;
- }
- }
- break;
- /*
- * A few other packet types which we do not support
- */
- case ACTION_INHIBIT: /* Bool Bool */
- /* Return success for the hell of it */
- break;
- case ACTION_RENAME_DISK:/* BSTR:NewName Bool */
- case ACTION_MORECACHE: /* #BufsToAdd Bool */
- case ACTION_WAIT_CHAR: /* Timeout, ticks Bool */
- case ACTION_FLUSH: /* writeout bufs, disk motor off */
- case ACTION_RAWMODE: /* Bool(-1:RAW 0:CON) OldState */
- default:
- fail:
- error = ERROR_ACTION_NOT_KNOWN;
- break;
- }
- if (packet) {
- if (error) {
- packet->dp_Res1 = DOS_FALSE;
- packet->dp_Res2 = error;
- }
- returnpacket(packet);
- }
- }
- }
- Delay(50); /* I wanna even see the debug message! */
- Forbid();
- if (packetsqueued() || GetHead(&FHBase)) {
- Permit();
- goto top; /* sorry... can't exit */
- }
-
- /*
- * Causes a new process to be created on next reference
- */
-
- DosNode->dn_Task = FALSE;
-
- /*
- * Remove Volume entry. Since DOS uses singly linked lists, we
- * must (ugg) search it manually to find the link before our
- * Volume entry.
- */
-
- {
- DOSINFO *di = BTOC(((ROOTNODE *)DOSBase->dl_Root)->rn_Info);
- register DEVLIST *dl;
- register void *dlp;
-
- dlp = &di->di_DevInfo;
- for (dl = BTOC(di->di_DevInfo); dl && dl != DevList; dl = BTOC(dl->dl_Next))
- dlp = &dl->dl_Next;
- if (dl == DevList) {
- *(BPTR *)dlp = dl->dl_Next;
- dosfree((ulong *)dl);
- } else {
- ;
- }
- }
-
- /*
- * closedown, fall of the end of the world
- *
- * (which is how you kill yourself if a PROCESS. A TASK would have
- * had to RemTask(NULL) itself).
- */
-
- if (CHan)
- DClose(CHan);
- CHan = 0;
- #ifdef DEBUG
- dbuninit();
- #endif
- CloseLibrary((LIB *)DOSBase);
- /*
- CloseLibrary(DResBase);
- */
- }
-
-
- /*
- * PACKET ROUTINES. Dos Packets are in a rather strange format as you
- * can see by this and how the PACKET structure is extracted in the
- * GetMsg() of the main routine.
- */
-
- void
- returnpacket(packet)
- PACKET *packet;
- {
- register struct Message *mess;
- register struct MsgPort *replyport;
-
- replyport = packet->dp_Port;
- mess = packet->dp_Link;
- packet->dp_Port = &DosProc->pr_MsgPort;
- mess->mn_Node.ln_Name = (char *)packet;
- mess->mn_Node.ln_Succ = NULL;
- mess->mn_Node.ln_Pred = NULL;
- PutMsg(replyport, mess);
- }
-
- /*
- * Are there any packets queued to our device?
- */
-
- int
- packetsqueued()
- {
- return ((void *)DosProc->pr_MsgPort.mp_MsgList.lh_Head !=
- (void *)&DosProc->pr_MsgPort.mp_MsgList.lh_Tail);
- }
-
- /*
- * Handle structure, locks, and manipulation.
- */
-
- HANDLE *
- GetHandleForLock(block)
- LOCK *block;
- {
- register LOCK *lock = BTOC(block);
- register HANDLE *handle;
-
- #ifdef DEBUG
- dbprintf("GetHandleForLock: %08lx ", lock);
- #endif
- if (lock) {
- handle = (HANDLE *)lock->fl_Key;
- #ifdef DEBUG
- dbprintf("Handle=%08lx (h=$%08lx)\n", handle, handle->Handle);
- #endif
- if (handle->Magic == MAGIC)
- return(handle);
- Alert(AT_Recovery|1, (char *)handle);
- }
- #ifdef DEBUG
- dbprintf("\n");
- #endif
- /*Alert(AT_Recovery|2, (char *)-2);*/
- return(&RFRoot);
- }
-
- void *
- GetLockForHandle(handle)
- HANDLE *handle;
- {
- register LOCK *lock = handle->Lock;
- register LOCKLINK *ln;
-
- #ifdef DEBUG
- dbprintf("GetLockForHandle: %08lx ", handle);
- #endif
- if (!lock) {
- lock = dosalloc(sizeof(LOCK));
- #ifdef DEBUG
- dbprintf("(allocate) %08lx\n", lock);
- #endif
- ln = AllocMem(sizeof(LOCKLINK), MEMF_PUBLIC|MEMF_CLEAR);
- AddHead((LIST *)&LCBase,(NODE *)ln);
- ln->Lock = lock;
- lock->fl_Link = (long)ln;
- lock->fl_Key = (long)handle;
- lock->fl_Access = ACCESS_READ;
- lock->fl_Task= &DosProc->pr_MsgPort;
- lock->fl_Volume = (BPTR)CTOB(DosNode);
-
- handle->Lock = lock;
- }
- #ifdef DEBUG
- dbprintf("Lock=%08lx\n", lock);
- #endif
- return((void *)CTOB(lock));
- }
-
- HANDLE *
- AllocHandle(name, rpkt)
- char *name;
- RtOpen *rpkt;
- {
- HANDLE *handle;
- register char *ptr;
-
- for (ptr = name + strlen(name) - 1; ptr >= name && *ptr != '/'; --ptr);
- ++ptr;
-
- handle = AllocMem(sizeof(HANDLE), MEMF_PUBLIC|MEMF_CLEAR);
- handle->Magic = MAGIC;
- handle->Handle= rpkt->Handle;
- handle->Type = rpkt->Type;
- handle->Prot = rpkt->Prot;
- handle->Size = rpkt->Size;
- handle->Name = AllocMem(strlen(ptr)+1, MEMF_PUBLIC);
- handle->Date = rpkt->Date;
- strcpy(handle->Name, ptr);
- AddHead((LIST *)&FHBase, (NODE *)handle);
-
- #ifdef DEBUG
- dbprintf("AllocHandle: %08lx '%s' h=$%08lx\n", handle, ptr, handle->Handle);
- #endif
- return(handle);
- }
-
- void
- FreeHandle(handle)
- HANDLE *handle;
- {
- #ifdef DEBUG
- dbprintf("FreeHandle: %08lx %08lx\n", handle, handle->Lock);
- #endif
- if (handle->Lock) {
- register LOCK *lock = handle->Lock;
- Remove((NODE *)lock->fl_Link);
- FreeMem((void *)lock->fl_Link, sizeof(LOCKLINK));
- dosfree((ulong *)lock);
- }
- Remove((NODE *)handle);
- handle->Magic = 0;
- FreeMem(handle->Name, strlen(handle->Name)+1);
- FreeMem(handle, sizeof(HANDLE));
- }
-
- /*
- * DOS MEMORY ROUTINES
- *
- * DOS makes certain assumptions about LOCKS. A lock must minimally be
- * a FileLock structure, with additional private information after the
- * FileLock structure. The longword before the beginning of the structure
- * must contain the length of structure + 4.
- *
- * NOTE!!!!! The workbench does not follow the rules and assumes it can
- * copy lock structures. This means that if you want to be workbench
- * compatible, your lock structures must be EXACTLY sizeof(struct FileLock).
- */
-
- void *
- dosalloc(bytes)
- reg ulong bytes;
- {
- reg ulong *ptr;
-
- bytes += 4;
- ptr = AllocMem(bytes, MEMF_PUBLIC|MEMF_CLEAR);
- *ptr = bytes;
- return(ptr+1);
- }
-
- void
- dosfree(ptr)
- register ulong *ptr;
- {
- --ptr;
- FreeMem(ptr, *ptr);
- }
-
- /*
- * Convert a BSTR into a normal string.. copying the string into buf.
- * I use normal strings for internal storage, and convert back and forth
- * when required.
- */
-
- char *
- bstos(bstr)
- ubyte *bstr;
- {
- static char buf[512];
- static char *ptr = buf;
-
- if (ptr == buf) /* switch which buffer to use */
- ptr = buf + 256;
- else
- ptr = buf;
-
- bstr = BTOC(bstr);
- BMov(bstr+1,ptr,*bstr);
- ptr[*bstr] = 0;
- return(ptr);
- }
-
- char *
- skipdevice(str)
- register char *str;
- {
- char *base = str;
-
- while (*str && *str != ':')
- ++str;
- if (*str == 0)
- str = base;
- else
- ++str;
- return(str);
- }
-
- /*
- * data = DoNetworkOp(&cmd, &len, data)
- */
-
- int
- DoNetworkOp(cmd, s, _slen, d, dlen, r, rlen)
- char cmd;
- int _slen;
- void *s;
- void *d;
- void *r;
- {
- ubyte slen = _slen;
- if (CHan) {
- if (DWrite(CHan, &cmd, 1) < 0)
- goto fail;
- if (DWrite(CHan, &slen, 1) < 0)
- goto fail;
- if (DWrite(CHan, &dlen, 4) < 0)
- goto fail;
- if (DWrite(CHan, s, slen) < 0)
- goto fail;
-
- if (dlen) {
- if (DWrite(CHan, d, dlen) < 0)
- goto fail;
- }
- if (r) {
- if (DRead(CHan, r, rlen) != rlen)
- goto fail;
- }
- return(0);
- }
- fail:
- if (CHan) {
- DClose(CHan);
- CHan = 0;
- }
- return(1);
- }
-
- #ifndef LATTICE
-
- #asm
-
- _mygeta4:
- far data
- lea __H1_org+32766,a4
- rts
-
- public __H0_org
-
- dseg
-
- public __H1_org
-
- cseg
- #endasm
-
- #endif
-
-
- #ifdef DEBUG /* note, doesn't work w/ Lattice */
-
- /*
- * DEBUG CODE
- */
-
-
- /* DEBUGGING */
- PORT *Dbport; /* owned by the debug process */
- PORT *Dback; /* owned by the DOS device driver */
- MSG DummyMsg; /* Dummy message that debug proc can use */
-
- /*
- * DEBUGGING CODE. You cannot make DOS library calls that access other
- * devices from within a DOS device driver because they use the same
- * message port as the driver. If you need to make such calls you must
- * create a port and construct the DOS messages yourself. I do not
- * do this. To get debugging info out another PROCESS is created to which
- * debugging messages can be sent.
- *
- * You want the priority of the debug process to be larger than the
- * priority of your DOS handler. This is so if your DOS handler crashes
- * you have a better idea of where it died from the debugging messages
- * (remember that the two processes are asyncronous from each other).
- */
-
- extern void debugproc();
-
- dbinit()
- {
- TASK *task = FindTask(NULL);
-
- Dback = CreatePort(NULL,NULL);
- CreateProc("DEV_DB", task->tc_Node.ln_Pri+1, CTOB(debugproc), 4096);
- WaitPort(Dback); /* handshake startup */
- GetMsg(Dback); /* remove dummy msg */
- dbprintf("Debugger running V1.10, 2 November 1987\n");
- dbprintf("Works with WORKBENCH!\n");
- }
-
- dbuninit()
- {
- MSG killmsg;
-
- if (Dbport) {
- killmsg.mn_Length = 0; /* 0 means die */
- PutMsg(Dbport,&killmsg);
- WaitPort(Dback); /* He's dead jim! */
- GetMsg(Dback);
- DeletePort(Dback);
-
- /*
- * Since the debug process is running at a greater priority, I
- * am pretty sure that it is guarenteed to be completely removed
- * before this task gets control again. Still, it doesn't hurt...
- */
-
- Delay(50); /* ensure he's dead */
- }
- }
-
- dbprintf(a,b,c,d,e,f,g,h,i,j)
- {
- char buf[256];
- MSG *msg;
-
- if (Dbport && !DBDisable) {
- sprintf(buf,a,b,c,d,e,f,g,h,i,j);
- msg = AllocMem(sizeof(MSG)+strlen(buf)+1, MEMF_PUBLIC|MEMF_CLEAR);
- msg->mn_Length = strlen(buf)+1; /* Length NEVER 0 */
- strcpy(msg+1,buf);
- PutMsg(Dbport,msg);
- }
- }
-
- /*
- * BTW, the DOS library used by debugmain() was actually openned by
- * the device driver. Note: DummyMsg cannot be on debugmain()'s stack
- * since debugmain() goes away on the final handshake.
- */
-
- void
- debugmain()
- {
- MSG *msg;
- short len;
- void *fh;
-
- mygeta4();
- Dbport = CreatePort(NULL,NULL);
- fh = Open("con:0/0/640/100/debugwindow", 1006);
- PutMsg(Dback, &DummyMsg);
- for (;;) {
- WaitPort(Dbport);
- msg = GetMsg(Dbport);
- len = msg->mn_Length;
- if (len == 0)
- break;
- --len; /* Fix length up */
- Write(fh, msg+1, len);
- FreeMem(msg,sizeof(MSG)+len+1);
- }
- Close(fh);
- DeletePort(Dbport);
- PutMsg(Dback,&DummyMsg); /* Kill handshake */
- }
-
- /*
- * The assembly tag for the DOS process: CNOP causes alignment problems
- * with the Aztec assembler for some reason. I assume then, that the
- * alignment is unknown. Since the BCPL conversion basically zero's the
- * lower two bits of the address the actual code may start anywhere around
- * the label.... Sigh.... (see CreatProc() above).
- */
-
- #asm
- public _debugproc
- public _debugmain
-
- cseg
- nop
- nop
- nop
- _debugproc:
- nop
- nop
- movem.l D2-D7/A2-A6,-(sp)
- jsr _debugmain
- movem.l (sp)+,D2-D7/A2-A6
- rts
- #endasm
-
-
- #endif
-
-
-